package learner.hmm;

import java.util.HashMap;
import java.util.Map;

/**
 * 
 * @author Geert
 *
 * @param <R> type of row of matrix
 * @param <C> type of column of matrix
 * @param <V> type of value of matrix
 */
public class Matrix<R , C> {
	
	private Map<R, Map<C, Double>> matrix;
	
	public Matrix () {
		matrix = new HashMap<R, Map<C, Double>>();
	}
	
	public Matrix (Map<R, Map<C, Double>> matrix) {
		this.matrix = matrix;
	}
	
	public Double get(R row, C column){
		if (!elementSet(row, column))
			return (double)0;
		return matrix.get(row).get(column);
	}
	
	private boolean elementSet(R row, C column) {
		if (! matrix.containsKey(row))
			return false;
		if (! matrix.get(row).containsKey(column))
			return false;
		return true;
	}

	public void setElement(R row, C column, Double value) {
		if (value > 1.02)
			throw new IllegalArgumentException("Value must be lower than 1. Value = " + value);
		if (value > 1)
			value = 1.0;
		if (! elementSet(row, column)) {
			initializeElement(row, column, value);
			return;
		}
		matrix.get(row).put(column, value);
	}

	private void initializeElement(R row, C column, Double value) {
		if (! matrix.containsKey(row)) {
			Map<C, Double> transitionsRow = new HashMap<C, Double>();
			transitionsRow.put(column, value);
			matrix.put(row, transitionsRow);
		} else {
			matrix.get(row).put(column, value);
		}	
	}
	
	
	
	public Map<R , Map <C, Double>> toMap() {
		return new HashMap<R , Map <C, Double>>(matrix);
	}

	public double sumRow(R row) {
		double sum = 0.0;
		if (matrix.get(row) == null) 
			return sum;
		else {
			for (Double element : matrix.get(row).values()) {
				sum += element;
			}
			return sum;
		}
	}
	
	

}
